﻿/*    
    This file is part of d-mixr.

    d-mixr is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    d-mixr is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with d-mixr.  If not, see <http://www.gnu.org/licenses/>.
*/

using System;
using System.Linq;
using System.Windows.Input;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using Dmixr.Model;
using Dmixr.View;
using System.Xml.Serialization;
using System.IO;

namespace Dmixr.ViewModel
{
    public class MainWindowViewModel: ViewModelBase
    {
        RelayCommand m_closeCommand;
        RelayCommand m_createChannelStrip;
        RelayCommand m_showAbout;

        public ObservableCollection<ChannelStripViewModel> ChannelStrips { get; set; }

        [XmlIgnore]
        public ObservableCollection<string> MidiInputs
        {
            get { return m_midiInputs; }
        }

        readonly ObservableCollection<string> m_midiInputs;

        [XmlIgnore]
        public ObservableCollection<string> MidiOutputs
        {
            get { return m_midiOutputs; }
        }

        readonly ObservableCollection<string> m_midiOutputs;

        [XmlAttribute]
        public string MidiInput
        {
            get
            {
                if (MidiSystem.Instance.InputDevice != null)
                {
                    return MidiSystem.Instance.InputDevice.Name; 
                }
                return "No Midi Input";
            }
            set
            {
                MidiSystem.Instance.InputDevice = Midi.InputDevice.InstalledDevices.FirstOrDefault(i => i.Name == value);
            }
        }

        [XmlAttribute]
        public string MidiOutput
        {
            get
            {
                if (MidiSystem.Instance.OutputDevice != null)
                {
                    return MidiSystem.Instance.OutputDevice.Name;
                }
                return "No Midi Output";
            }
            set
            {
                MidiSystem.Instance.OutputDevice = Midi.OutputDevice.InstalledDevices.FirstOrDefault(i => i.Name == value);
            }
        }

        public MainWindowViewModel()
        {
            ChannelStrips = new ObservableCollection<ChannelStripViewModel>();
            ChannelStrips.CollectionChanged += OnChannelStripsChanged;

            m_midiInputs = new ObservableCollection<string>(Midi.InputDevice.InstalledDevices.Select(c => c.Name));

            m_midiOutputs = new ObservableCollection<string>(Midi.OutputDevice.InstalledDevices.Select(c => c.Name));

            MidiInputs.Insert(0, "No Midi Input");
            MidiOutputs.Insert(0, "No Midi Output");

            // To do unregister to event
            AudioSystem.Instance.NewAudioSessionEvent += OnNewAudioSessionHandler;
        }

        void OnNewAudioSessionHandler()
        {
            System.Console.WriteLine("New Sessions created.");

            foreach (ChannelStripViewModel c in ChannelStrips.ToList().FindAll(c => !c.IsSessionActive ))
            {
                c.TryReconnect();
            }
        }

        void OnChannelStripsChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
            if (e.NewItems != null && e.NewItems.Count != 0)
            {
            }

            if (e.OldItems != null && e.OldItems.Count != 0)
            {
            }
        }

        public ICommand CloseCommand
        {
            get
            {
                if (m_closeCommand == null)
                    m_closeCommand = new RelayCommand(param => this.OnRequestClose());

                return m_closeCommand;
            }
        }

        public event EventHandler RequestClose;

        void OnRequestClose()
        {
            EventHandler handler = this.RequestClose;
            if (handler != null)
                handler(this, EventArgs.Empty);
        }


        public ICommand CreateChannelStripCommand
        {
            get
            {
                if (m_createChannelStrip == null)
                    m_createChannelStrip = new RelayCommand(param => this.OnCreateChannelStrip());

                return m_createChannelStrip;
            }
        }

        public ICommand ShowAboutCommand
        {
            get
            {
                if (m_showAbout == null)
                    m_showAbout = new RelayCommand(param => this.OnShowAbout());

                return m_showAbout;
            }
        }

        void OnShowAbout()
        {
            var myAboutWindow = new AboutWindow();
            myAboutWindow.Show();
        }

        void OnDestroyChannelStrip(ChannelStripViewModel toDelete)
        {
            toDelete.RequestDeleteEvent -= OnDestroyChannelStrip;
            ChannelStrips.Remove(toDelete);
            toDelete.strip.Term();
            toDelete.Term();
        }

        void OnCreateChannelStrip()
        {
            ChannelStrip strip = new ChannelStrip(); 
            ChannelStripViewModel vm = new ChannelStripViewModel(strip);
            vm.Init();
            ChannelStrips.Add(vm);

            strip.Init();
            vm.RequestDeleteEvent += OnDestroyChannelStrip;
        }

        public void Pickle()
        {
            XmlSerializer serializer = new XmlSerializer(typeof(MainWindowViewModel));
            TextWriter textWriter = new StreamWriter(Dmixr.Preferences.GetPreferenceFile());
            serializer.Serialize(textWriter, this);
            textWriter.Close();
        }

        public void Relive()
        {
            foreach(ChannelStripViewModel vm in ChannelStrips)
            {
                vm.Init();
                vm.strip.Init();
                vm.RequestDeleteEvent += OnDestroyChannelStrip;
            }
        }
    }
}
